﻿Imports System
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Drawing.Imaging
Public Class Cam

    Private Const WM_USER As Integer = &H400 '用户消息开始号，偏移地址:1024
    Private Const WS_CHILD As Integer = &H40000000
    Private Const WS_VISIBLE As Integer = &H10000000
    Private Const WM_CAP_START As Integer = WM_USER
    Private Const WM_CAP_STOP As Integer = WM_CAP_START + 68 '终止视频捕获
    Private Const WM_CAP_DRIVER_CONNECT As Integer = WM_CAP_START + 10 '连接一个视频驱动，成功返回真(1)。连接驱动后，不一定就能显示视频，还要保证摄像头硬件连接良好、未被其他程序使用。
    Private Const WM_CAP_DRIVER_DISCONNECT As Integer = WM_CAP_START + 11 '断开视频窗口与驱动的连接
    Private Const WM_CAP_SAVEDIB As Integer = WM_CAP_START + 25
    Private Const WM_CAP_GRAB_FRAME As Integer = WM_CAP_START + 60
    Private Const WM_CAP_SEQUENCE As Integer = WM_CAP_START + 62 '开始录像
    Private Const WM_CAP_FILE_SET_CAPTURE_FILEA As Integer = WM_CAP_START + 20
    Private Const WM_CAP_SEQUENCE_NOFILE As Integer = WM_CAP_START + 63
    Private Const WM_CAP_SET_OVERLAY As Integer = WM_CAP_START + 51 '使窗口处于叠加模式。使叠加模式有效也会自动地使预览模式失效
    Private Const WM_CAP_SET_PREVIEW As Integer = WM_CAP_START + 50 '发送给捕捉窗口来使预览模式有效或者失效
    Private Const WM_CAP_SET_CALLBACK_VIDEOSTREAM As Integer = WM_CAP_START + 6 '在流捕获期间，当一个新的视频缓存区可用的时候就调用它
    Private Const WM_CAP_SET_CALLBACK_ERROR As Integer = WM_CAP_START + 2 '当出错回调函数
    Private Const WM_CAP_SET_CALLBACK_STATUSA As Integer = WM_CAP_START + 3
    Private Const WM_CAP_SET_CALLBACK_FRAME As Integer = WM_CAP_START + 5 '帧预览回调函数
    Private Const WM_CAP_SET_SCALE As Integer = WM_CAP_START + 53 '来使预览模式的缩放有效或者无效
    Private Const WM_CAP_SET_PREVIEWRATE As Integer = WM_CAP_START + 52 '发送给捕捉窗口来设置在预览模式下帧的显示频率
    Public Const WM_CAP_GET_CAPSTREAMPTR = WM_CAP_START + 1
    Public Const WM_CAP_SET_CALLBACK_STATUS = WM_CAP_START + 3 '当状态（status）改变的时回调函数
    Public Const WM_CAP_SET_CALLBACK_YIELD = WM_CAP_START + 4 '在流捕获期间的回调函数
    Public Const WM_CAP_SET_CALLBACK_WAVESTREAM = WM_CAP_START + 7 '在流捕获期间，当一个新的音频缓存区可用的时候就调用它
    Public Const WM_CAP_GET_USER_DATA = WM_CAP_START + 8 '获取：数据关联到一个捕捉窗口
    Public Const WM_CAP_SET_USER_DATA = WM_CAP_START + 9 '设置：数据关联到一个捕捉窗口
    Public Const WM_CAP_DRIVER_GET_NAME = WM_CAP_START + 12
    Public Const WM_CAP_DRIVER_GET_VERSION = WM_CAP_START + 13
    Public Const WM_CAP_DRIVER_GET_CAPS = WM_CAP_START + 14
    Public Const WM_CAP_FILE_SET_CAPTURE_FILE = WM_CAP_START + 20 '设置当前的捕捉文件
    Public Const WM_CAP_FILE_GET_CAPTURE_FILE = WM_CAP_START + 21 '得到当前的捕捉文件
    Public Const WM_CAP_FILE_ALLOCATE = WM_CAP_START + 22 '为捕捉文件预分配空间,从而可以减少被漏掉的帧
    Public Const WM_CAP_FILE_SAVEAS = WM_CAP_START + 23 '将捕捉文件保存为另一个用户指定的文件。这个消息不会改变捕捉文件的名字和内容,
    Public Const WM_CAP_FILE_SET_INFOCHUNK = WM_CAP_START + 24 '可以把信息块例如文本或者自定义数据插入avi文件。同样用这个消息也可以清除avi文件中的信息块
    Public Const WM_CAP_FILE_SAVEDIB = WM_CAP_START + 25 '把从帧缓存中复制出图像存为设备无关位图书馆（DIB),应用程序也可以使用这两个单帧捕捉消息来编辑帧序列，
    Public Const WM_CAP_EDIT_COPY = WM_CAP_START + 30 '1054：把缓存中图像复制到剪贴板中
    Public Const WM_CAP_SET_AUDIOFORMAT = WM_CAP_START + 35 '设置音频格式。设置时传入一个WAVEFORMAT、WAVEFORMATEX、或PCMWAVEOFMAT结构的指针
    Public Const WM_CAP_GET_AUDIOFORMAT = WM_CAP_START + 36 '来得到音频数据的格式和该格式结构体的大小。默认的捕捉音频格式是mono、8-bit和11kHZ PCM
    Public Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41 '对话框：视频格式
    Public Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42 '对话框：视频源，枚举视频源，控制颜色、对比度、饱和度的改变。需视频驱动程序支技
    Public Const WM_CAP_DLG_VIDEODISPLAY = WM_CAP_START + 43 '对话框：视频显示？控制视频捕捉过程中视频在显示器上的显示。对捕捉数据无影响，但会影响数了信号表达式
    Public Const WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44 '给捕捉窗口来得到视频格式的结构和该结构的大小。
    Public Const WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45 '用来设置视频格式
    Public Const WM_CAP_DLG_VIDEOCOMPRESSION = WM_CAP_START + 46 '对话框：视频压缩
    Public Const WM_CAP_GET_STATUS = WM_CAP_START + 54
    Public Const WM_CAP_SET_SCROLL = WM_CAP_START + 55 '如果是在预览模式或者叠加模式，还可以通过本消息发送给窗口，在窗口里的用户区域设置视频帧的滚动条的位置
    Public Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61
    Public Const WM_CAP_SET_SEQUENCE_SETUP = WM_CAP_START + 64
    Public Const WM_CAP_GET_SEQUENCE_SETUP = WM_CAP_START + 65
    Public Const WM_CAP_SET_MCI_DEVICE = WM_CAP_START + 66
    Public Const WM_CAP_GET_MCI_DEVICE = WM_CAP_START + 67
    Public Const WM_CAP_ABORT = WM_CAP_START + 69  '暂停录像捕获？，成功返回真
    Public Const WM_CAP_SINGLE_FRAME_OPEN = WM_CAP_START + 70
    Public Const WM_CAP_SINGLE_FRAME_CLOSE = WM_CAP_START + 71
    Public Const WM_CAP_SINGLE_FRAME = WM_CAP_START + 72
    Public Const WM_CAP_PAL_OPEN = WM_CAP_START + 80
    Public Const WM_CAP_PAL_SAVE = WM_CAP_START + 81
    Public Const WM_CAP_PAL_PASTE = WM_CAP_START + 82
    Public Const WM_CAP_PAL_AUTOCREATE = WM_CAP_START + 83
    Public Const WM_CAP_PAL_MANUALCREATE = WM_CAP_START + 84
    '// Following added post VFW 1.1
    Public Const WM_CAP_SET_CALLBACK_CAPCONTROL = WM_CAP_START + 85
    '// Defines end of the message range
    Public Const WM_CAP_END = WM_CAP_SET_CALLBACK_CAPCONTROL
    Private hWndC As IntPtr
    Private bStat As Boolean = False

    Private mControlPtr As IntPtr
    Private mWidth As Integer
    Private mHeight As Integer
    Private mLeft As Integer
    Private mTop As Integer

    <DllImport("avicap32.dll")> _
    Private Shared Function capCreateCaptureWindowA(ByVal lpszWindowName() As Byte, ByVal dwStyle As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hWndParent As IntPtr, ByVal nID As Integer) As IntPtr
    End Function

    <DllImport("avicap32.dll")> _
    Private Shared Function capGetVideoFormat(ByVal hWnd As IntPtr, ByVal psVideoFormat As IntPtr, ByVal wSize As Integer) As Integer
    End Function

    <DllImport("User32.dll")> _
    Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Boolean
    End Function
    '//设置图像大小
    Function capDlgVideoFormat() As Boolean
        capDlgVideoFormat = SendMessage(hWndC, WM_CAP_DLG_VIDEOFORMAT, 0, 0)
    End Function
    '//设置视频源参数
    Function capDlgVideoSource() As Boolean
        capDlgVideoSource = SendMessage(hWndC, WM_CAP_DLG_VIDEOSOURCE, 0, 0)
    End Function
    '//显示视频源
    Function capDlgVideoDisplay() As Boolean
        capDlgVideoDisplay = SendMessage(hWndC, WM_CAP_DLG_VIDEODISPLAY, 0, 0)
    End Function
    '//设置视频压缩
    Function capDlgVideoCompression() As Boolean
        capDlgVideoCompression = SendMessage(hWndC, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0)
    End Function

    '接上节

    '/// <summary>
    '/// 初始化摄像头
    '/// </summary>
    '/// <param name="handle">控件的句柄</param>
    '/// <param name="left">开始显示的左边距</param>
    '/// <param name="top">开始显示的上边距</param>
    '/// <param name="width">要显示的宽度</param>
    '/// <param name="height">要显示的长度</param>
    Public Sub New(ByVal handle As IntPtr, ByVal left As Integer, ByVal top As Integer, ByVal width As Integer, ByVal height As Integer)
        mControlPtr = handle
        mWidth = width
        mHeight = height
        mLeft = left
        mTop = top
    End Sub

    '/// <summary>
    '/// 开始显示图像
    '/// </summary>
    Public Sub Start()
        'If bStat Then
        'eturn
        'End If
        ' bStat = True
        Dim lpszName(99) As Byte

        hWndC = capCreateCaptureWindowA(lpszName, WS_CHILD Or WS_VISIBLE, mLeft, mTop, mWidth, mHeight, mControlPtr, 0)

        If hWndC.ToInt32() <> 0 Then
            SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0)
            SendMessage(hWndC, WM_CAP_SET_CALLBACK_ERROR, 0, 0)
            SendMessage(hWndC, WM_CAP_SET_CALLBACK_STATUSA, 0, 0)
            SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0)
            SendMessage(hWndC, WM_CAP_SET_SCALE, 1, 0)
            SendMessage(hWndC, WM_CAP_SET_PREVIEWRATE, 6, 0)
            SendMessage(hWndC, WM_CAP_SET_OVERLAY, 1, 0)
            SendMessage(hWndC, WM_CAP_SET_PREVIEW, 1, 0)
        End If

        ' Return
    End Sub

    '/// <summary>
    '/// 停止显示
    '/// </summary>
    Public Sub [Stop]()
        SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0)
        bStat = False
    End Sub

    '/// <summary>
    '/// 抓图
    '/// </summary>
    '/// <param name="path">要保存bmp文件的路径</param>
    Public Sub GrabImage(ByVal path As String)
        Dim hBmp As IntPtr = Marshal.StringToHGlobalAnsi(path)
        SendMessage(hWndC, WM_CAP_SAVEDIB, 0, hBmp.ToInt64())
    End Sub

    '/// <summary>
    '/// 录像
    '/// </summary>
    '/// <param name="path">要保存avi文件的路径</param>
    Public Sub Kinescope(ByVal path As String)
        Dim hBmp As IntPtr = Marshal.StringToHGlobalAnsi(path)
        SendMessage(hWndC, WM_CAP_FILE_SET_CAPTURE_FILEA, 0, hBmp.ToInt64())
        SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0)
    End Sub

    '/// <summary>
    '/// 停止录像
    '/// </summary>
    Public Sub StopKinescope()
        SendMessage(hWndC, WM_CAP_STOP, 0, 0)
    End Sub
End Class


